package com.umeox.watch.moto.alarm;

import android.content.ContentValues;
import android.os.Parcel;
import android.os.Parcelable;

import androidx.annotation.NonNull;

import com.umeox.moto.common.log.Logger;
import com.umeox.moto.common.utils.DateUtils;
import com.umeox.watch.moto.alarm.base.BaseApp;
import com.umeox.watch.moto.alarm.base.Constants;
import com.umeox.watch.moto.dataservice.DataProvider;

import java.util.Calendar;

public class AlarmDetail implements Parcelable, Comparable<AlarmDetail>, Cloneable {

    public static final Creator<AlarmDetail> CREATOR = new Creator<AlarmDetail>() {
        @Override
        public AlarmDetail createFromParcel(Parcel source) {
            return new AlarmDetail(source);
        }

        @Override
        public AlarmDetail[] newArray(int size) {
            return new AlarmDetail[size];
        }
    };
    /**
     * 闹钟ID
     */
    private long id;
    /**
     * 服务器闹钟ID
     */
    private long alarmId;
    /**
     * 闹钟名称
     */
    private String alarmName;
    /**
     * 闹钟时间，取值范围（指定日期：2017-06-16 21:30:00，周重复：21:30，月重复：15 21:30，年重复：03-15 21:30）
     */
    private String alarmTime;
    /**
     * 重复标记，取值范围（0：指定日期，1：按周重复，2：按月重复，3：按年重复）
     */
    private int repeatFlag;
    /**
     * 按周重复表达，由7位为0或1字符组成，第一个字符为星期天，依次至星期六，1代表有设置，0代表无设置
     */
    private String repeatExpression;
    /**
     * 铃声类型
     * 0：默认铃声（暂设置为0）
     */
    private int ringType;
    /**
     * 闹钟开关
     * 0：关闭
     * 1：打开
     */
    private int state;
    /**
     * 闹钟任务图标。
     * 指定的任务图标，使用数字字符串代表。
     * 0代表WakeUp,1代表Play time
     * 2代表Bath,3代表School Time
     * 4代表Blush Teeth,5代表Bed Time
     * 6代表Ready to bed,7代表Food
     * 8代表HomeWork,9代表Chores
     */
    private String ringSrc;
    /**
     * 闹钟具体时间戳，从不重复的闹钟才会把这个值存入数据库，用来判断闹钟是否有效
     */
    private long alarmTimeInMillis;

    public AlarmDetail() {
    }

    protected AlarmDetail(Parcel in) {
        this.id = in.readLong();
        this.alarmId = in.readLong();
        this.alarmName = in.readString();
        this.alarmTime = in.readString();
        this.repeatFlag = in.readInt();
        this.repeatExpression = in.readString();
        this.ringType = in.readInt();
        this.state = in.readInt();
        this.ringSrc = in.readString();
        this.alarmTimeInMillis = in.readLong();
    }

    public static AlarmDetail convertFromValues(ContentValues values) {
        if (values == null) {
            return null;
        }
        AlarmDetail detail = new AlarmDetail();
        detail.id = values.getAsLong(DataProvider.AlarmProvider.ID);
        detail.alarmId = values.getAsLong(DataProvider.AlarmProvider.ALARM_ID);
        detail.alarmName = values.getAsString(DataProvider.AlarmProvider.ALARM_NAME);
        detail.alarmTime = values.getAsString(DataProvider.AlarmProvider.ALARM_TIME);
        detail.repeatFlag = values.getAsInteger(DataProvider.AlarmProvider.REPEAT_FLAG);
        detail.repeatExpression = values.getAsString(DataProvider.AlarmProvider.REPEAT_EXPRESSION);
        detail.ringType = values.getAsInteger(DataProvider.AlarmProvider.RING_TYPE);
        detail.state = values.getAsInteger(DataProvider.AlarmProvider.ALARM_STATE);
        detail.ringSrc = values.getAsString(DataProvider.AlarmProvider.RING_SRC);
        detail.alarmTimeInMillis = values.getAsLong(DataProvider.AlarmProvider.ALARM_TIMEINMILLIS);
        return detail;
    }

    public final ContentValues bindToInsertValues() {
        ContentValues values = new ContentValues();
        values.put(DataProvider.AlarmProvider.ALARM_ID, getAlarmId());
        values.put(DataProvider.AlarmProvider.ALARM_NAME, getAlarmName());
        values.put(DataProvider.AlarmProvider.ALARM_TIME, getAlarmTime());
        values.put(DataProvider.AlarmProvider.REPEAT_FLAG, getRepeatFlag());
        values.put(DataProvider.AlarmProvider.REPEAT_EXPRESSION, getRepeatExpression());
        values.put(DataProvider.AlarmProvider.RING_TYPE, getRingType());
        values.put(DataProvider.AlarmProvider.ALARM_STATE, getState());
        values.put(DataProvider.AlarmProvider.RING_SRC, getRingSrc());
        values.put(DataProvider.AlarmProvider.ALARM_TIMEINMILLIS, getAlarmTimeInMillis());
        return values;
    }

    public AlarmDetail later(int min) throws CloneNotSupportedException {
        AlarmDetail temp = (AlarmDetail) clone();
        temp.setState(1);
        temp.setAlarmId(Integer.MAX_VALUE);
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.MINUTE, min);
        temp.setAlarmTime(DateUtils.formatTime(cal.getTimeInMillis()));
        return temp;
    }

    public long insert() {
        long rowId = DataProvider.addAlarm(bindToInsertValues());
        Logger.d("添加闹钟>>>[" + rowId + "]");
        if (rowId > 0) {
            BaseApp.getInstance().scheduleAlarm();
        }
        return rowId;
    }

    public boolean update() {
        boolean result = DataProvider.updateAlarm(bindToInsertValues(), DataProvider.AlarmProvider.ID + "=?", new String[]{String.valueOf(id)}) > 0;
        Logger.d("修改闹钟>>>[" + id + "][" + result + "]");
        if (result) {
            BaseApp.getInstance().scheduleAlarm();
        }
        return result;
    }

    public boolean updateWithoutNotify() {
        Logger.d("修改闹钟->" + id);
        return DataProvider.updateAlarm(bindToInsertValues(), DataProvider.AlarmProvider.ID + "=?", new String[]{String.valueOf(id)}) > 0;
    }

    public boolean delete() {
        Logger.d("删除闹钟->" + id);
        boolean result = DataProvider.deleteAlarm(DataProvider.AlarmProvider.ID + "=?", new String[]{String.valueOf(id)}) > 0;
        if (result) {
            BaseApp.getInstance().scheduleAlarm();
        }
        return result;
    }

    public boolean deleteWithoutNotify() {
        Logger.d("删除闹钟->" + id);
        return DataProvider.deleteAlarm(DataProvider.AlarmProvider.ID + "=?", new String[]{String.valueOf(id)}) > 0;
    }

    @Override
    public int compareTo(@NonNull AlarmDetail another) {
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.HOUR_OF_DAY, getHour());
        cal.set(Calendar.MINUTE, getMinute());
        long temp1 = cal.getTimeInMillis();
        cal.set(Calendar.HOUR_OF_DAY, another.getHour());
        cal.set(Calendar.MINUTE, another.getMinute());
        long temp2 = cal.getTimeInMillis();
        return Long.compare(temp1, temp2);
    }

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public boolean isRepeat() {
        return repeatFlag == 1;
    }

    public int getRepeatFlag() {
        return repeatFlag;
    }

    /**
     * 设置闹钟重复周期时，修改该标记
     */
    public void setRepeatFlag(int repeatFlag) {
        this.repeatFlag = repeatFlag;
    }

    public String getHourString() {
        if (Utils.is24HourFormatTime(getAlarmTime())) {
            return getAlarmTime().split(":")[0];
        } else {
            return DateUtils.formatDateTime(System.currentTimeMillis(), "HH");
        }
    }

    public int getHour() {
        return Integer.parseInt(getHourString());
    }

    public String getMinuteString() {
        if (Utils.is24HourFormatTime(getAlarmTime())) {
            return getAlarmTime().split(":")[1];
        } else {
            return DateUtils.formatDateTime(System.currentTimeMillis(), "mm");
        }
    }

    public int getMinute() {
        return Integer.parseInt(getMinuteString());
    }

    public boolean notExists() {
        return id > 0 && alarmId == 0;
    }

    public long getAlarmId() {
        return alarmId;
    }

    public void setAlarmId(long alarmId) {
        this.alarmId = alarmId;
    }

    public String getAlarmName() {
        return alarmName;
    }

    public void setAlarmName(String alarmName) {
        this.alarmName = alarmName;
    }

    public String getAlarmTime() {
        return alarmTime;
    }

    public void setAlarmTime(String alarmTime) {
        this.alarmTime = alarmTime;
    }

    public String getRepeatExpression() {
        return repeatExpression;
    }

    public void setRepeatExpression(String repeatExpression) {
        setRepeatFlag(Constants.ALARM_NOREPEAT_EXP.equals(repeatExpression) ? 0 : 1);
        this.repeatExpression = repeatExpression;
    }

    public int getRingType() {
        return ringType;
    }

    public void setRingType(int ringType) {
        this.ringType = ringType;
    }

    public int getState() {
        return state;
    }

    public void setState(int state) {
        this.state = state;
    }

    public boolean isValid() {
        return getState() == 1;
    }

    public String getRingSrc() {
        return ringSrc;
    }

    public void setRingSrc(String ringSrc) {
        this.ringSrc = ringSrc;
    }

    public long getAlarmTimeInMillis() {
        return alarmTimeInMillis;
    }

    public void setAlarmTimeInMillis(long alarmTimeInMillis) {
        this.alarmTimeInMillis = alarmTimeInMillis;
    }

    @Override
    public String toString() {
        return "AlarmDetail{" +
                "id=" + id +
                ", alarmId=" + alarmId +
                ", alarmName='" + alarmName + '\'' +
                ", alarmTime='" + alarmTime + '\'' +
                ", repeatFlag=" + repeatFlag +
                ", repeatExpression='" + repeatExpression + '\'' +
                ", ringType=" + ringType +
                ", state=" + state +
                ", ringSrc=" + ringSrc +
                ", alarmTimeInMillis=" + alarmTimeInMillis +
                '}';
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeLong(this.id);
        dest.writeLong(this.alarmId);
        dest.writeString(this.alarmName);
        dest.writeString(this.alarmTime);
        dest.writeInt(this.repeatFlag);
        dest.writeString(this.repeatExpression);
        dest.writeInt(this.ringType);
        dest.writeInt(this.state);
        dest.writeString(this.ringSrc);
        dest.writeLong(this.alarmTimeInMillis);
    }
}
